package com.javasm.inceptor;

import com.javasm.annotation.Permission;
import com.javasm.domain.AuthenConstant;
import com.javasm.domain.LoginUser;
import com.javasm.exception.AuthenticationException;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.buf.StringUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;


/**
 * 拦截器实现权限注解驱动
 *
 * @author admin
 */
@Slf4j
public class AuthorityInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) {

        if (!(handler instanceof HandlerMethod)){
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        String className =method.getDeclaringClass().getName();
        log.info("当前请求的方法为：{}",className+"."+method.getName());
        Permission annotation = method.getAnnotation(Permission.class);
        if (annotation == null) {
            if (method.getName().contains("login")||method.getName().contains("logout")){
                return true;
            }
             //如果注解为null, 则拦截，不给通过，并提示没有权限注解
            throw new AuthenticationException("权限异常，该接口没有添加任何权限信息");
        }
        //拿到自定义权限上的注解
        AuthenConstant[] authenticationMethod = annotation.authentication();
        // 去和框架上的注解去比对，如果正确，则放行，否则报错提示没有权限
        Authentication authentication1 = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication1.getPrincipal();
        String userName = loginUser.getUser().getUserName();
        String methodName = method.getName();
        // 如果权限注解上只有一个权限并且该权限为ALL,则表示所有用户都可以访问
        if (authenticationMethod.length == 1 && "all".equals(authenticationMethod[0].getAuthentication())){
            this.logUserDetails(className, userName, methodName,authentication1.getAuthorities());
            return true;
        }
        Collection<? extends GrantedAuthority> authorities = authentication1.getAuthorities();
        for (GrantedAuthority userAuthority : authorities) {
            String userAuthorityAuthority = userAuthority.getAuthority();
            for (AuthenConstant authenConstant : authenticationMethod) {
                if (authenConstant.getAuthentication().equals(userAuthorityAuthority)){
                    this.logUserDetails(className, userName, methodName, authorities);
                    return true;
                }
            }
        }
        throw new AuthenticationException("用户没有权限！");
    }

    private void logUserDetails(String className, String userName, String methodName, Collection<? extends GrantedAuthority> authorities) {
        log.info("当前登录用户为：{}", userName);
        ArrayList<String> authenStr = new ArrayList<>();
        for (GrantedAuthority authen : authorities) {
            authenStr.add(authen.getAuthority());
        }
        String authens = "["+StringUtils.join(authenStr)+"]";
        log.info("当前用户拥有的权限:{}", authens);
        log.info("当前用户访问的方法名为:{}", className +"."+ methodName);
    }
}